using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace FixLineEndings
{
	class Program
	{
		static List<string> extensionsToFix = new List<string>();
		static Program()
		{
			extensionsToFix.Add(".cpp");
			extensionsToFix.Add(".hpp");
			extensionsToFix.Add(".c");
			extensionsToFix.Add(".h");
			extensionsToFix.Add(".xml");
			extensionsToFix.Add(".buildng");
		}

		static void Main(string[] args)
		{
			try
			{
				string rootDir;
				if (args.Length == 1)
					rootDir = Path.Combine(Directory.GetCurrentDirectory(), args[0]);
				else if (args.Length == 0)
					rootDir = Directory.GetCurrentDirectory();
				else
					throw new Exception("Too many arguments specified.");

				FixDirectoryRecursive(rootDir);
			}
			catch (Exception err)
			{
				Console.Error.WriteLine(err.Message);
			}
		}

		static void FixDirectoryRecursive(string dir)
		{
			if (dir[0] == '.')
				return;

			string[] files = Directory.GetFiles(dir);

			foreach (string file in files)
			{
				FileInfo fileInfo = new FileInfo(file);
				if (extensionsToFix.Contains(fileInfo.Extension.ToLower()))
				{
					string fileToFix = Path.Combine(dir, file);
					FixFile(fileToFix);
				}
			}

			string[] childDirs = Directory.GetDirectories(dir);
			foreach (string childDir in childDirs)
			{
				string childPath = Path.Combine(dir, childDir);
				FixDirectoryRecursive(childPath);
			}
		}

		static void FixFile(string fileName)
		{
			MemoryStream fixedData = new MemoryStream();
			using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
			{
				TextReader reader = new StreamReader(fileStream);
				
				TextWriter writer = new StreamWriter(fixedData);
				writer.NewLine = "\n";
				while (true)
				{
					string line = reader.ReadLine();
					if (line == null)
						break;
					writer.WriteLine(line);
				}
				writer.Flush();
			}
			fixedData.Flush();
			fixedData.Position = 0;

			using (FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
			{
				int numBytes = (int)fixedData.Length;
				byte[] buffer = new byte[numBytes];
				fixedData.Read(buffer, 0, numBytes);
				fileStream.Write(buffer, 0, numBytes);
			}
		}
	}
}
